package tu.java.login;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.codec.binary.Hex;

import tu.java.db.DBConnManager;
import tu.java.menu.Menu;

public class User {
	
	
	
	public enum accountType {
		User, Casher, Admin, Guest
	}
	
	private int					userId;
	private String				firstName;
	private String				lastName;
	private String				email;
	private String				password;
	private static final String	salt	= "bg1dklrj3toJ9uik2flk7gkhr639otughe9dkussi34thgird";
	private accountType			type;
	private String				userAcess;
	
	
	
	public User() {
		firstName = "";
		lastName = "";
		email = "";
		password = "";
		type = accountType.Guest;
		userAcess = getUserAcess(type);
		userId = 1;
	}
	
	
	
	public User(String firstName, String lastName, String email, String password, accountType type) {
		this.firstName = firstName;
		this.lastName = firstName;
		this.email = email;
		this.password = password;
		this.type = type;
		this.userAcess = getUserAcess(type);
	}
	
	
	
	private String GetHashedPassword() {
		MessageDigest md;
		String saltedPass = password + salt;
		try {
			md = MessageDigest.getInstance("SHA-512");
			byte[] hashedPass = md.digest(saltedPass.getBytes());
			return new String(Hex.encodeHex(hashedPass));
		}
		catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	
	
	public boolean Login(HttpServletRequest request) {
		HttpSession session = request.getSession(false);
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			conn = DBConnManager.getInstance().getConnection();
			pstmt = conn.prepareStatement("SELECT CS02_USER_ID,CS02_USER_EMAIL,CS01_USER_TYPE,CS02_USER_FNAME,CS02_USER_LNAME from TS02_USERS WHERE CS02_USER_EMAIL=? AND CS02_USER_PASSWORD=?");
			pstmt.setString(1, email);
			pstmt.setString(2, GetHashedPassword());
			rs = pstmt.executeQuery();
			if (rs.next()) {
				User u = new User();
				u.userId = rs.getInt(1);
				u.email = rs.getString(2);
				u.type = getType(rs.getInt(3));
				u.firstName = rs.getString(4);
				u.lastName = rs.getString(5);
				u.setUserAcess(getUserAcess(u.getType()));
				session.setAttribute("userObj", u);
				return true;
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			DBConnManager.getInstance().close(rs);
			DBConnManager.getInstance().close(pstmt);
			DBConnManager.getInstance().freeConnection(conn);
		}
		return false;
	}
	
	
	
	public boolean RegisterUser() {
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			conn = DBConnManager.getInstance().getConnection();
			pstmt = conn.prepareStatement("SELECT CS02_USER_ID from TS02_USERS WHERE CS02_USER_EMAIL=? ");
			pstmt.setString(1, email);
			rs = pstmt.executeQuery();
			if (rs.next()) {
				return false;
			}
			pstmt = null;
			
			pstmt = conn.prepareStatement("INSERT INTO TS02_USERS (CS02_USER_FNAME,CS02_USER_LNAME,CS02_USER_EMAIL,CS02_USER_PASSWORD,CS01_USER_TYPE) VALUES(?,?,?,?,?)");
			pstmt.setString(1, firstName);
			pstmt.setString(2, lastName);
			pstmt.setString(3, email);
			pstmt.setString(4, GetHashedPassword());
			pstmt.setInt(5, getType(type));
			pstmt.executeUpdate();
			userAcess = getUserAcess(type);
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			DBConnManager.getInstance().close(rs);
			DBConnManager.getInstance().close(pstmt);
			DBConnManager.getInstance().freeConnection(conn);
		}		
		return true;
	}
	
	
	
	public static User searchUser(int userId) {
		User u = new User();
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			conn = DBConnManager.getInstance().getConnection();
			StringBuilder sql = new StringBuilder();
			sql.append(" select CS02_USER_ID, CS02_USER_EMAIL, CS02_USER_PASSWORD,");
			sql.append(" CS01_USER_TYPE, CS02_TIME_DATE, CS02_USER_FNAME, CS02_USER_LNAME");
			sql.append("  from TUDB.TS02_USERS where CS02_USER_ID = ?");
			
			pstmt = conn.prepareStatement(sql.toString());
			
			pstmt.setInt(1, userId);
			
			rs = pstmt.executeQuery();
			
			if (rs.next()) {
				
				u.setEmail(rs.getString(2));
				u.setPassword(rs.getString(3));
				u.setFirstName(rs.getString(6));
				u.setLastName(rs.getString(7));
				
				accountType type = accountType.Guest;
				
				switch (rs.getInt(4)) {
				case 101:
					type = accountType.User;
				case 102:
					type = accountType.Casher;
				case 103:
					type = accountType.Admin;
					
				}
				
				u.setType(type);
				u.userId = userId;
			}
			
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			DBConnManager.getInstance().close(rs);
			DBConnManager.getInstance().close(pstmt);
			DBConnManager.getInstance().freeConnection(conn);
		}
		return u;
	}
	
	
	
	public String getFirstName() {
		return firstName;
	}
	
	
	
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	
	
	
	public String getLastName() {
		return lastName;
	}
	
	
	
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	
	
	
	public String getEmail() {
		return email;
	}
	
	
	
	public void setEmail(String email) {
		this.email = email;
	}
	
	
	
	public String getPassword() {
		return password;
	}
	
	
	
	public void setPassword(String password) {
		this.password = password;
	}
	
	
	
	public accountType getType() {
		return type;
	}
	
	
	
	public accountType getType(int index) {
		
		switch (index) {
		case 101:
			return accountType.User;
		case 102:
			return accountType.Casher;
		case 103:
			return accountType.Admin;
		default:
			return accountType.Guest;
		}
	}
	
	
	
	public int getType(accountType type) {
		
		switch (type) {
		case User:
			return 101;
		case Casher:
			return 102;
		case Admin:
			return 103;
		}
		return 0;
	}
	
	
	
	public void setType(accountType type) {
		this.type = type;
	}
	
	
	
	private String getUserAcess(accountType type) {
		
		switch (type) {
		case User:
			return Menu.USER_ACESS;
		case Casher:
			return Menu.CASHER_ACESS;
		case Admin:
			return Menu.ADMIN_ACESS;
		}
		return Menu.GUEST_ACESS;
	}
	
	
	
	public String getUserAcess() {
		return userAcess;
	}
	
	
	
	public void setUserAcess(String userAcess) {
		this.userAcess = userAcess;
	}
	
	
	
	public int getUserId() {
		return userId;
	}
	
	
	
	public void setUserId(int userId) {
		this.userId = userId;
	}
	
}
